%{ /* -------------------------- Prologue ----------------------------------- */


/*
 * Departamento de Ciência da Computação
 * Tradutores 02/2009 - turma A
 * Professor Marco Aurélio
 * Alunos: Danilo Gaby Andersen Trindade - 06/82039
 *         Alex Rodrigo de Oliveira      - 06/30403
 */

    #include <cstdio>
	#include "tipos.h"
    #include "scanner.h"
    #include "parser.h"
	#include "actions.h"
    
    void yyerror(const char* txt);
%}


/* --------------------------- Declarations --------------------------------- */


%right '='
%token IF ELSE WHILE BREAK CONTINUE RETURN DEF GLOBAL INT ID
        INDENT DEDENT NEWLINE  ':' ',' '(' ')' '[' ']'
%left OR
%left AND
%token NOT
%token EQ LT GT LE GE NE
%left '+' '-'
%left '*' '%' DIV
%token _NEG
%right POW
%left _INDEX
%left _CALL
%token _PAREN
%token _LIST


%% /* ------------------------------ Rules ---------------------------------- */


cmd_globs:	  cmd_glob
			| cmd_glob cmd_globs
;

cmd_glob:	  atr_glob NEWLINE
			| funcao
			| NEWLINE
;

cmd_locs:	  cmd_loc
			| cmd_loc cmd_locs
;

cmd_loc:	  atr NEWLINE					{  }
			| decl NEWLINE					{  }
			| chamada NEWLINE				{  }
			| cmd_if						{  }
			| cmd_while						{  }
			| BREAK NEWLINE					{  }
			| CONTINUE NEWLINE				{  }
			| RETURN exp NEWLINE			{  }
			| NEWLINE
;

atr_glob:	  lval_glob '=' INT				{ $$ = act_atr($1, $3, 1); }
			| lval_glob '=' list			{ $$ = act_atr($1, $3, 2); }
;

lval_glob:	  ID							{ $$ = act_lval_id0((char*)$1); }
;

atr:		  lval '=' exp					{ $$ = act_atr($1, $3, -1); }
;

lval:		  ID							{ $$ = act_lval_id1((char*)$1); }
			| ID '[' exp ']'				{  }
;

decl:		  GLOBAL ID						{  }
;

exp:		  atom							{ $$ = $1; }
			| exp OR exp					{  }
			| exp AND exp					{  }
			| NOT exp						{  }
			| exp EQ exp					{  }
			| exp LT exp					{  }
			| exp GT exp					{  }
			| exp LE exp					{  }
			| exp GE exp					{  }
			| exp NE exp					{  }
			| exp '+' exp					{ $$ = act_exp_add($1, $3); }
			| exp '-' exp					{ $$ = act_exp_sub($1, $3); }
			| exp '*' exp					{ $$ = act_exp_mult($1, $3); }
			| exp '%' exp					{ $$ = act_exp_mod($1, $3); }
			| exp DIV exp					{ $$ = act_exp_div($1, $3); }
			| '-' exp %prec _NEG			{  }
			| exp POW exp					{  }
			| '(' exp ')' %prec _PAREN		{  }
;

atom:		  ID							{ $$ = act_id((char*)$1); }
			| INT							{ $$  = act_atom_int($1); }
			| list %prec _LIST				{  }
			| ID '[' exp ']' %prec _INDEX	{  }
			| chamada %prec _CALL			{  }
;

list:		  '[' args ']'					{  }
;

args:		  /* vazio */
			| exp							{  }
			| exp ',' args					{  }
;

chamada:	  ID '(' args ')'				{  }
;

cmd_if:		  IF exp ':' NEWLINE
				INDENT cmd_locs DEDENT
			  cmd_else						{  }
;

cmd_else:	  /* vazio */
			| ELSE ':' NEWLINE
				INDENT cmd_locs DEDENT		{  }
;

cmd_while:	  WHILE exp ':' NEWLINE
				INDENT cmd_locs DEDENT		{  }
;

funcao:		  fn_prefix NEWLINE
				INDENT cmd_locs DEDENT		{ $$ = act_fn(); }
;

fn_prefix:	  DEF ID '(' params ')' ':'		{ $$ = act_fn_id((char*)$2); }
;

params:		  /* vazio */					{  }
			| params1						{  }
;

params1:	  ID							{ $$ = act_param((char*)$1); }
			| ID ',' params1				{ $$ = act_param((char*)$1); }
;


%% /* ----------------------------- Epilogue -------------------------------- */


/*
 * Diz ao Bison o que fazer quando ocorrer um erro.
 */
void yyerror(const char *txt) {
	if (yytext[0] == 0) return;
    fprintf(stderr, "%s on line %d, token \"%s\"\n", txt, here, yytext);
	exit(1);
}


/*
 * Só chama o inicializador do léxico e do semântico.
 */
void yy_init() {
	lex_init();
	act_init();
}


/*
 * Só chama os outros.
 */
void yy_end() {
	lex_end();
	act_end();
}
